home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / DTS.Lib / Init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-14  |  9.5 KB  |  297 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:         DTS.Lib
  5. ** File:            init.c
  6. ** Some code from:  Traffic Light 2.0 (2.0 version by Keith Rollin)
  7. ** Modified by:     Eric Soldan
  8. **
  9. ** Copyright © 1989-1991 Apple Computer, Inc.
  10. ** All rights reserved.
  11. */
  12.  
  13. /* You may incorporate this sample code into your applications without
  14. ** restriction, though the sample code has been provided "AS IS" and the
  15. ** responsibility for its operation is 100% yours.  However, what you are
  16. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  17. ** after having made changes. If you're going to re-distribute the source,
  18. ** we require that you make it clear in the source that the code was
  19. ** descended from Apple Sample Code, but that you've made changes. */
  20.  
  21.  
  22.  
  23. /*****************************************************************************/
  24.  
  25.  
  26.  
  27. #ifndef OBSOLETE
  28. #define OBSOLETE
  29. #endif
  30.  
  31. #include "DTS.Lib2.h"
  32. #include "DTS.Lib.protos.h"
  33.  
  34. #ifndef __ERRORS__
  35. #include <Errors.h>
  36. #endif
  37.  
  38. #ifndef __GESTALTEQU__
  39. #include <GestaltEqu.h>
  40. #endif
  41.  
  42.  
  43.  
  44. /*****************************************************************************/
  45.  
  46.  
  47.  
  48. /* Set up the whole world, including global variables, Toolbox managers, and
  49. ** menus.  We also create our one application window at this time.  Since
  50. ** window storage is non-relocateable, how and when to allocate space for
  51. ** windows is very important so that heap fragmentation does not occur. */
  52.  
  53. /* The code that used to be part of ForceEnvirons has been moved into this
  54. ** module.  If an error is detected, instead of merely doing an ExitToShell,
  55. ** which leaves the user without much to go on, we call DeathAlert, which puts
  56. ** up a simple alert that just says an error occurred and then calls
  57. ** ExitToShell.  Since there is no other cleanup needed at this point if an
  58. ** error is detected, this form of error-handling is acceptable.  If more
  59. ** sophisticated error recovery is needed, an exception mechanism, such as is
  60. ** provided by Signals, can be used. */
  61.  
  62.  
  63.  
  64. /*****************************************************************************/
  65.  
  66.  
  67.  
  68. /* NOTE:  The “g” prefix is used to emphasize that a variable is global. */
  69.  
  70. OSType    gDocCreator;
  71. Boolean    gQuitApplication;
  72. Boolean gNoFinderPrint;
  73.  
  74. short    gMenuBar   = rMenuBar;
  75. short    gAppleMenu = mApple;
  76.  
  77. extern Boolean        gHasAppleEvents, gNoDefaultDocument;
  78. extern RgnHandle    gCursorRgn;
  79. extern short        gPrintPage;
  80. extern OSType        gAppWindowType;
  81. extern TreeObjHndl    gWindowFormats;
  82. extern DescType        gAERequiredType;
  83.  
  84. typedef void (*callBack)(void);
  85.  
  86.  
  87.  
  88. /*****************************************************************************/
  89. /*****************************************************************************/
  90.  
  91.  
  92.  
  93. /* Given minHeap and minSpace values, get stuff going.  Also, we are passed
  94. ** in two procedure pointers.  If these are not nil, they are called at
  95. ** intermediate points during the initialization process.  The first proc
  96. ** is called after the Utilities.c standard initialization is complete.  The
  97. ** second proc is called very near the end of the initialization, but just
  98. ** prior to the menus being initialized. */
  99.  
  100. #pragma segment Initialize
  101. void    Initialize(short moreMasters, long minHeap, long minSpace, ProcPtr init1, ProcPtr init2)
  102. {
  103.     long    total, contig;
  104.  
  105.     StandardInitialization(moreMasters);
  106.  
  107.     if (init1)
  108.         (*(callBack)init1)();    /* Give app a chance to do some init stuff here. */
  109.  
  110.     /* Make sure that the machine has at least 128K ROMs.
  111.     ** If it doesn’t, exit. */
  112.  
  113.     if ((gMachineType < gestaltMac512KE) || (!gHasWaitNextEvent))
  114.         DeathAlert(rBadNewsStrings, sWimpyMachine);
  115.  
  116.     /* We used to make a check for memory at this point by examining
  117.     ** ApplLimit, ApplicZone, and StackSpace and comparing that to the minimum
  118.     ** size we told MultiFinder we needed.  This did not work well because it
  119.     ** assumed too much about the relationship between what we asked
  120.     ** MultiFinder for and what we would actually get back, as well as how to
  121.     ** measure it.  Instead, we will use an alternate method comprised of
  122.     ** two steps. */
  123.  
  124.     /* It is better to first check the size of the application heap against a
  125.     ** value that you have determined is the smallest heap the application can
  126.     ** reasonably work in.  This number should be derived by examining the
  127.     ** size of the heap that is actually provided by MultiFinder when the
  128.     ** minimum size requested is used.  The derivation of the minimum size
  129.     ** requested from MultiFinder is described in DTS.Lib.h.  The check should
  130.     ** be made because the preferred size can end up being set smaller than
  131.     ** the minimum size by the user.  This extra check acts to ensure that
  132.     ** your application is starting from a solid memory foundation. */
  133.  
  134.     if ((long)GetApplLimit() - (long)ApplicationZone() < minHeap)
  135.         DeathAlert(rBadNewsStrings, sHeapTooSmall);
  136.  
  137.     /* Next, make sure that enough memory is free for your application to run.
  138.     ** It is possible for a situation to arise where the heap may have been of
  139.     ** required size, but a large scrap was loaded which left too little
  140.     ** memory.  To check for this, call PurgeSpace and compare the result with
  141.     ** a value that you have determined is the minimum amount of free memory
  142.     ** your application needs at initialization.  This number can be derived
  143.     ** several different ways.  One way that is fairly straightforward is to
  144.     ** run the application in the minimum size configuration as described
  145.     ** previously.  Call PurgeSpace at initialization and examine the value
  146.     ** returned.  However, you should make sure that this result is not being
  147.     ** modified by the scrap’s presence.  You can do that by calling ZeroScrap
  148.     ** before calling PurgeSpace.  Make sure to remove that call before
  149.     ** shipping, though. */
  150.  
  151.     PurgeSpace(&total, &contig);
  152.     if (total < minSpace)
  153.         DeathAlert(rBadNewsStrings, sNoFreeRoomInHeap);
  154.  
  155.     /* The extra benefit to waiting until after the Toolbox Managers have been
  156.     ** initialized to check memory is that we can now give the user an alert
  157.     ** to tell him/her what happened.  Although it is possible that the memory
  158.     ** situation could be worsened by displaying an alert, MultiFinder would
  159.     ** gracefully exit the application with an informative alert if memory
  160.     ** became critical.  Here we are acting more in a preventative manner to
  161.     ** avoid future disaster from low-memory problems. */
  162.  
  163.     if (init2)
  164.         (*(callBack)init2)();    /* Give app a chance to do some init stuff here. */
  165.  
  166.     gDocCreator = gSignature;
  167.         /* Copy the app creator type read by Utilities.c.  By copying it, the app can
  168.         ** change it if necessary to coerce various file I/O functions that use
  169.         ** gDocCreator to generate a file of a different creator type. */
  170.  
  171.     StandardMenuSetup(gMenuBar, gAppleMenu);
  172.  
  173.     qd.randSeed = TickCount();
  174. }
  175.  
  176.  
  177.  
  178. /*****************************************************************************/
  179.  
  180.  
  181.  
  182. /* This function handles the documents selected in the finder, either for
  183. ** loading or for printing.  This is only if we don't have AppleEvents.
  184. ** If we have AppleEvents, then this will all be done automatically via
  185. ** those wonderful AppleEvent thingies. */
  186.  
  187. #pragma segment Initialize
  188. void    StartDocuments(void)
  189. {
  190.     OSErr        err;
  191.  
  192. #ifndef powerc
  193.     short        i;
  194.     short        whatToDo;
  195.     short        numberOfFiles;
  196.     AppFile        theAppFile;
  197.     FSSpec        fileSpec;
  198.     long        ignore, wkind;
  199.     FileRecHndl    frHndl;
  200.     WindowPtr    docWindow, fwindow;
  201.     TreeObjHndl    wobj;
  202.     long        attr;
  203. #endif
  204.  
  205.     if (gNoDefaultDocument) return;
  206.     err = noErr;
  207.  
  208. #ifndef powerc
  209.     if (!gHasAppleEvents) {
  210.  
  211.         CountAppFiles(&whatToDo, &numberOfFiles);
  212.         if (gNoFinderPrint) whatToDo = appOpen;
  213.  
  214.         if (numberOfFiles > 0) {
  215.  
  216.             gAERequiredType = (whatToDo == appPrint) ? 'pdoc' : 'odoc';        /* To inform the application what is gong on. */
  217.  
  218.             for (i = 1; (i <= numberOfFiles) && (!err); ++i) {
  219.                 GetAppFiles(i, &theAppFile);
  220.                 ClrAppFiles(i);
  221.                 err = GetWDInfo(theAppFile.vRefNum, &fileSpec.vRefNum, &fileSpec.parID, &ignore);
  222.  
  223.                 if (err)
  224.                     HCenteredAlert(rErrorAlert, nil, gAlertFilterUPP);
  225.  
  226.                 else {
  227.                     pcpy(fileSpec.name, theAppFile.fName);
  228.                     err = OpenDocument(&frHndl, &fileSpec, fsRdWrPerm);
  229.                     if (!err) {
  230.                         docWindow = (*frHndl)->fileState.window;
  231.                         if (!docWindow) {
  232.                             gPrintPage = whatToDo;
  233.                                 /* Open the window off-screen if we are printing. */
  234.                             err = DoNewWindow(frHndl, &docWindow, FrontWindow(), (WindowPtr)-1);
  235.                             if (err)
  236.                                 DisposeDocument(frHndl);
  237.                             else {
  238.                                 if (gPrintPage) {
  239.                                     err = PrintDocument(frHndl, (i == 1), (i == 1));
  240.                                     DisposeDocument(frHndl);
  241.                                     DisposeAnyWindow(docWindow);
  242.                                 }
  243.                             }
  244.                             gPrintPage = 0;
  245.                         }
  246.                         else {
  247.                             wkind   = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  248.                             fwindow = FrontWindowOfType(wkind, true);
  249.                             CleanSendInFront(docWindow, fwindow);
  250.                         }
  251.                     }
  252.                     if ((err) && (err != userCanceledErr)) {
  253.                         HCenteredAlert(rErrorAlert, nil, gAlertFilterUPP);
  254.                         break;
  255.                     }
  256.                 }
  257.             }
  258.  
  259.             gAERequiredType = 0;
  260.             if (whatToDo == appPrint) gQuitApplication = true;
  261.         }
  262.         else {
  263.             err = noErr;
  264.             if (gWindowFormats) {
  265.                 for (i = (*gWindowFormats)->numChildren; i;) {
  266.                     wobj = GetChildHndl(gWindowFormats, --i);
  267.                     attr = mDerefWFMT(wobj)->attributes;
  268.                     if (!(attr & kwRuntimeOnlyDoc)) {
  269.                         if (attr & kwAutoNew) {
  270.                             err = NewDocumentWindow(&frHndl, mDerefWFMT(wobj)->sfType, true);
  271.                             if (err) break;
  272.                         }
  273.                     }
  274.                 }
  275.             }
  276.             else {
  277.                 if (!gNoDefaultDocument) {
  278.                     err = NewDocument(&frHndl, gAppWindowType, true);
  279.                     if (!err) {
  280.                         if (frHndl) {
  281.                             err = DoNewWindow(frHndl, nil, FrontWindow(), (WindowPtr)-1);
  282.                             if (err)
  283.                                 DisposeDocument(frHndl);
  284.                         }
  285.                     }
  286.                 }
  287.             }
  288.         }
  289.     }
  290. #endif
  291.  
  292.     DonePrinting();        /* Clean up after printing, if we did any. */
  293. }
  294.  
  295.  
  296.  
  297.